package com.bjy.qa.service.functionaltest.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bjy.qa.dao.functionaltest.CatalogDao;
import com.bjy.qa.dao.functionaltest.TestResultCaseDao;
import com.bjy.qa.dao.functionaltest.TestResultSuiteDao;
import com.bjy.qa.dao.functionaltest.TestSuiteDao;
import com.bjy.qa.entity.Response;
import com.bjy.qa.entity.functionaltest.*;
import com.bjy.qa.enumtype.CatalogType;
import com.bjy.qa.enumtype.RunStatus;
import com.bjy.qa.enumtype.TaskStatus;
import com.bjy.qa.exception.MyException;
import com.bjy.qa.service.functionaltest.ITestExecuteService;
import com.bjy.qa.service.functionaltest.ITestResultSuiteService;
import com.bjy.qa.util.TimeUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

@org.springframework.stereotype.Service
public class TestExecuteService extends ServiceImpl<TestSuiteDao, TestSuite> implements ITestExecuteService {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Resource
    private CatalogDao catalogDao;

    @Resource
    TestSuiteDao testSuiteDao;

    @Resource
    TestResultSuiteDao testResultSuiteDao;

    @Resource
    TestResultCaseDao testResultCaseDao;

    @Resource
    ITestResultSuiteService iTestResultSuiteService;

    @Override
    public List<FullTree> listTree(CatalogType type, CatalogType caseType, Long projectId, Long testSuitesId, Long testResultId, Long parentId) {
        if (testSuitesId == null || testSuitesId == 0) {
            throw new MyException("查询 测试套件 tree 失败：testSuitesId 不能为空");
        }
        if (testResultId == null) {
            TestResultSuite testResultSuite = testResultSuiteDao.getTestResultSuiteByProjectIdAndSid(projectId, testSuitesId);
            if (testResultSuite == null) {
                throw new MyException("查询 测试套件 tree 失败：该套件还没创建 测试结果表数据 testSuitesId: " + testSuitesId);
            }
            testResultId = testResultSuite.getId();
        }

        if (type == CatalogType.TEST_CASE || type == CatalogType.INTERFACE_TEST_CASE) {
            return recursiveQueryTree("ft_test_case", type,type, caseType, projectId, testSuitesId, testResultId, parentId);
        } else {
            throw new MyException("查询 tree 上某个type所有数据列表失败：type 未知，type: " + type + ", type.value: " + type.getValue());
        }
    }

    private List<FullTree> recursiveQueryTree(String elementTableName, CatalogType catalogType, CatalogType elementType, CatalogType caseType, Long projectId, Long testSuitesId, Long testResultId, Long parentId) {
        List<FullTree> fullTrees = null;
        if ("ft_test_case".equals(elementTableName)) {
            fullTrees = catalogDao.listTestSuiteCheckedTestCaseTree(catalogType, elementType, caseType, projectId, testSuitesId, testResultId, parentId);
        } else {
            throw new MyException("查询 tree 上某个type所有数据列表失败：elementTableName 未知，elementTableName: " + elementTableName);
        }

        for (FullTree fullTree : fullTrees) {
            if (fullTree.getIsCatalog()) {
                fullTree.setChildren(recursiveQueryTree(elementTableName, catalogType, elementType, caseType, projectId, testSuitesId, testResultId, fullTree.getId()));
            }
        }

        // 去掉空目录
        Iterator<FullTree> iterator = fullTrees.iterator();
        while (iterator.hasNext()) {
            FullTree fullTree = iterator.next();
            if(fullTree.getIsCatalog() && (fullTree.getChildren() == null || fullTree.getChildren().size() == 0)) {
                iterator.remove();
            }
        }

        return fullTrees;
    }

    @Override
    public Response<String> updateCaseStatus(TestExecuteDataDTO testExecuteDataDTO , String runUser) {
        TestSuite testSuite = testSuiteDao.selectById(testExecuteDataDTO.getSuiteId());

        if (testSuite == null) {
            throw new MyException("Suite ID 不存在！");
        }

        TestResultSuite testResultSuite = testResultSuiteDao.getTestResultSuiteByProjectIdAndSid(testSuite.getProjectId(), testExecuteDataDTO.getSuiteId());
        if (testResultSuite == null) {
            throw new MyException("更新测试用例执行状态 失败：该套件还没创建 测试结果表数据 testSuitesId: " + testExecuteDataDTO.getSuiteId());
        }

        // 更新 ft_test_result_case表
        TestResultCase testResultCase = testResultCaseDao.getTestResultCase(testResultSuite.getId(), testExecuteDataDTO.getCid());
        if (testResultCase == null) {
            testResultCase = new TestResultCase();
            testResultCase.setCid(testExecuteDataDTO.getCid());
            testResultCase.setRid(testResultSuite.getId());
            testResultCase.setStatus(testExecuteDataDTO.getCaseStatus());
            testResultCase.setAgent(0L);
            testResultCaseDao.insert(testResultCase);
        } else {
            testResultCase.setStatus(testExecuteDataDTO.getCaseStatus());
            testResultCase.setAgent(0L);
            testResultCaseDao.updateById(testResultCase);
        }

        Long resultId = testResultSuite.getId();
        // 套件运行完毕后更新 suite 表
        if (testResultSuiteDao.countRunningTestcase(testResultSuite.getId()) == 0) {
            testResultSuite.setEndAt(new Date());
            testResultSuite.setTotalTime(TimeUtil.getTimeDiff(testResultSuite.getCreatedAt(), new Date()));
            testResultSuite.setStatus(testResultSuiteDao.getTestResultStatus(resultId));
            testResultSuite.setUpdatedAt(null);
            testResultSuite.setCreatedAt(null);
            iTestResultSuiteService.updateById(testResultSuite);

            // 用例执行完后，当用例的最大状态>4，把测试套件的结果置为失败，当<4时，把测试套件结果置为成功
            if (testResultSuiteDao.getTestResultStatus(resultId) > RunStatus.PASSED.getValue()){
                testSuite.setStatus(TaskStatus.END_FAILED.getValue());
            } else {
                testSuite.setStatus(TaskStatus.END_SUCCESS.getValue());
            }
            // 更新test suite 状态
            testSuiteDao.updateById(testSuite);
        }

        return Response.success("执行成功！");
    }

}
